<?php
/**
 * Author:xsc
 * Time:2023/9/7 17:06
 */

namespace App\Service\Common;

use App\Service\BaseService;
use Illuminate\Support\Facades\Http;

class TestService extends BaseService
{

    public $cipher_algo = 'aes-128-ecb';

    public $open_public_key;

    public $open_private_key;

    public $public_key;

    public $private_key;

    public $url = 'http://sandnft-openapi-uat.sand.com.cn/';

    public function __construct()
    {
        $this->open_public_key = base_path() . '/keys/self/public.pem';
        $this->open_private_key = base_path() . '/keys/self/private.pem';
    }

    public function merchantsInfo()
    {
        $url = 'api/openapi/v1/merchants/info';

        $data = [
            'mid' => '6888806000506',
        ];

        $res = $this->request($url, $data);
        print_r($res);
        die;
    }

    /**
     * 请求
     * @param $url
     * @param $data
     * @return mixed
     * Author:xsc
     * Time:2023/9/25 13:29
     */
    public function request($url, $data)
    {
        $params = [
            'access_mode' => 'platform',
            'access_mid'  => '8888000001',
            'timestamp'   => time(),
            'data'        => $data,
        ];

        //生成aes_key
        $aes_key = $this->getAesKey();

        //1.用aes_key加密data
        $params['data'] = $this->aesEncrypt($params['data'], $aes_key);

        //2.用开放平台公钥加密aes_key
        $params['encryptKey'] = $this->rsaEncrypt($this->open_public_key, $aes_key);

        //3.用商户私钥生成sign
        $params['sign'] = $this->sign($params['data'], $this->private_key);

        $response = Http::post($this->url . $url, $params);
        $res = $response->body();
        $res = json_decode($res, true);

        if ($res['error_code'] == 0) {
            //1.验签
            $check = $this->checkSign($res['data'], $res['sign'], $this->open_public_key);

            //2.商户私钥解密得到aes_key
            $aes_key = $this->rsaDecrypt($this->private_key, $res['encryptKey']);

            //3.aes_key解密data得到响应体
            $resp = $this->aesDecrypt($res['data'], $aes_key);
            $res['data'] = json_decode($resp, true)['data'];
        }

        return $res;
    }


    /**
     * 生成一个随机key
     * @param int $length
     * @return false|string
     * Author:xsc
     * Time:2023/9/25 10:58
     */
    public function getAesKey(int $length = 16)
    {
        $token = '';
        $token_length = round($length * 4 / 3);

        for ($i = 0; $i < $token_length; ++$i) {
            $token .= chr(rand(32, 1024));
        }

        $token = base64_encode(str_shuffle($token));

        return substr($token, 0, $length);
    }

    /**
     * aes加密
     * @param array $data
     * @param string $aes_key
     * @return string
     * Author:xsc
     * Time:2023/9/25 10:58
     */
    public function aesEncrypt(array $data, string $aes_key)
    {
        ksort($data);

        $encrypt_key = openssl_encrypt(json_encode($data, 256), $this->cipher_algo, $aes_key, OPENSSL_RAW_DATA);

        return base64_encode($encrypt_key);
    }

    /**
     * aes解密
     * @param string $data
     * @param string $aes_key
     * @return false|string
     * Author:xsc
     * Time:2023/9/25 10:59
     */
    public function aesDecrypt(string $data, string $aes_key)
    {
        return openssl_decrypt(base64_decode($data), $this->cipher_algo, $aes_key, OPENSSL_RAW_DATA);
    }

    /**
     * 用公钥对aes_key进行rsa加密
     * @param string $public_key
     * @param string $aes_key
     * @return string
     * Author:xsc
     * Time:2023/9/25 10:59
     */
    public function rsaEncrypt(string $public_key, string $aes_key)
    {
        openssl_public_encrypt($aes_key, $encrypted_data, $public_key, OPENSSL_PKCS1_PADDING);

        return base64_encode($encrypted_data);
    }

    /**
     * 用私钥解密得到aes_key
     * @param string $private_key
     * @param string $encrypted_data
     * @return string
     * Author:xsc
     * Time:2023/9/25 10:59
     */
    public function rsaDecrypt(string $private_key, string $encrypted_data)
    {
        openssl_private_decrypt(base64_decode($encrypted_data), $decrypted_data, $private_key, OPENSSL_PKCS1_PADDING);

        return $decrypted_data;
    }

    /**
     * 用私钥生成签名
     * @param string $data
     * @param string $private_key
     * @return string
     * Author:xsc
     * Time:2023/9/25 10:59
     */
    public function sign(string $data, string $private_key)
    {
        $resource = openssl_pkey_get_private($private_key);
        openssl_sign($data, $sign, $resource);
        openssl_free_key($resource);
        return base64_encode($sign);
    }

    /**
     * 用公钥校验签名
     * @param string $data
     * @param string $sign
     * @param string $public_key
     * @return bool
     * Author:xsc
     * Time:2023/9/25 10:59
     */
    public function checkSign(string $data, string $sign, string $public_key)
    {
        $resource = openssl_pkey_get_public($public_key);
        $result = openssl_verify($data, base64_decode($sign), $resource);
        openssl_free_key($resource);

        if ($result != 1) {
            return false;
        }
        return true;
    }
}
